package leet59spiralmatrix2

func GenerateMatrix(n int) [][]int {
	// 1. 先定义一个二维数组来存放结果
	result := make([][]int, n)
	for i := range result {
		result[i] = make([]int, n)
	}
	// 2. 定义一个变量来记录当前的数字
	num := 1
	// 3. 定义一个变量来记录当前的方向，以及当前方向上的行列变化
	dir := 0                                                // 0表示向右，1表示向下，2表示向左，3表示向上
	directions := [][]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}} // 对应dir的不同的前进方向，row和col的变化，要么不变，要么加1，要么减1
	// 4. 定义一个变量来记录当前所处的行和列，该坐标会基于自身以及边界值决定下一个坐标的row和col。
	row, col := 0, 0
	// 5. 定义一个变量来记录当前的边界
	left, right, top, bottom := 0, n-1, 0, n-1
	// 肯定是要执行 n*n次的循环，因为每个位置都要填充数字，所以我们就用num来判断是否要继续循环。
	for num <= n*n {
		result[row][col] = num
		num++
		// 当前坐标基于边界值来决定移动方向。（移动方向决定了下一个坐标的row和col）
		// 这里的边界值是动态变化的，随着row和col的变化而变化。
		if dir == 0 && col == right {
			// 如果当前方向向右，但是列碰到了右边界，那么就要改变方向，变成向下。
			dir = (dir + 1) % 4
			top++ // 此处的方向变化会导致上边界的缩小，所以要加1
		} else if dir == 1 && row == bottom {
			// 如果当前方向向下，但是行碰到了下边界，那么就要改变方向，变成向左。
			dir = (dir + 1) % 4
			right-- // 此处的方向变化会导致右边界的缩小，所以要减1
		} else if dir == 2 && col == left {
			// 如果当前方向向左，但是列碰到了左边界，那么就要改变方向，变成向上。
			dir = (dir + 1) % 4
			bottom-- // 此处的方向变化会导致下边界的缩小，所以要减1
		} else if dir == 3 && row == top {
			// 如果当前方向向上，但是行碰到了上边界，那么就要改变方向，变成向右。
			dir = (dir + 1) % 4
			left++ // 此处的方向变化会导致上边界的缩小，所以要加1
		}

		// 确定了方向之后，就可以根据每个方向上的col和row的变化规则来更新当前的坐标了。
		row += directions[dir][0]
		col += directions[dir][1]
	}
	return result
}
